package com.rockcent.mall.controller;

import com.rockcent.common.common.JsonResult;
import com.rockcent.common.common.PageResult;
import com.rockcent.common.common.RestDoing;
import com.rockcent.common.controller.BaseController;
import com.rockcent.common.domain.enumclass.Whether;
import com.rockcent.common.utils.DateFormatUtils;
import com.rockcent.common.utils.DateUtils;
import com.rockcent.mall.Routes;
import com.rockcent.mall.helper.UserHelper;
import com.rockcent.mall.lib.domain.Product;
import com.rockcent.mall.lib.domain.enumclass.MerchantOrderSourceType;
import com.rockcent.mall.lib.domain.enumclass.ProductSourceType;
import com.rockcent.mall.lib.domain.enumclass.ProductType;
import com.rockcent.mall.lib.domain.enumclass.StatististicsType;
import com.rockcent.mall.lib.dto.MerchantProductStatisticsDto;
import com.rockcent.mall.lib.dto.UserInfoDto;
import com.rockcent.mall.lib.repository.MerchantProductRepository;
import com.rockcent.service.MerchantProductStatisticsService;
import org.apache.commons.lang3.EnumUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.*;

/**
 * Created by Marco on 16-12-13.
 * 产品统计
 */
@RestController
public class MerchantProductStatisticsController extends BaseController {

    private final Logger log = LoggerFactory.getLogger(MerchantProductStatisticsController.class);

    @Autowired
    private UserHelper userHelper;

    @Autowired
    private MerchantProductStatisticsService merchantProductStatisticsService;

    @Autowired
    private MerchantProductRepository merchantProductRepository;

    /**
     * @api {get}/merchant/product/statistics 产品统计
     * @apiGroup B端 merchant product statistics
     * @apiVersion 1.0.0
     * @apiHeader {String} userToken 用户token
     * @apiHeader {String} domain 请求域名
     *
     * @apiParam {String} searchDateType YESTERDAY("昨天"), WEEK("最近一周"), MONTH("最近一个月"), QUATER("最近三个月")
     * @apiParam {String} startDate 开始时间
     * @apiParam {String} endDate 结束时间
     * @apiParam {String} productSourceType ALL("全部"),SELF("自营"),MARKET("分销") 产品来源类型
     * @apiParam {String} type ALL("全部"),GOODS("商品"),SERVICE("服务") 类型
     *
     * @apiSuccess {Integer} clickCount 访问次数
     * @apiSuccess {Integer} visitorCount 访客人数
     * @apiSuccess {Long} orderCount 下单件数
     * @apiSuccess {Long} orderPayCount 支付件数
     * @apiSuccess {Long} verificationCustomerCount 核销人数
     * @apiSuccess {Long} verificationCount 核销数量
     * @apiSuccess {String} orderConversionRate 下单转化率
     * @apiSuccess {String} orderVerifiCationConversionRate 核销转化率
     * @apiSuccess {List} viewCountMonthList 按月访问次数　chartType=visit
     * @apiSuccess {List} saleCountMonthList 按月下单数量  chartType=sale
     * @apiSuccess {List} verifyCountMonthList 按月核销数量  chartType=verify
     * @apiSuccess {List} viewCustomerCountMonthList 按月访问人数  chartType=visit
     * @apiSuccess {List} saleCustomerMonthList 按月下单人数  chartType=sale
     * @apiSuccess {List} verifyCustomerMonthList 按月核销人数  chartType=verify
     * @apiSuccess {List} orderConversionRateMonthList 按月下单转化率 chartType=orderRate
     * @apiSuccess {List} orderVerifyConversionRateMonthList 按月核销转化率 chartType=verifyRate
     *
     * @apiSuccess {Long} quantity 数量－访问次数
     * @apiSuccess {String} dateStr 数量－日期
     * @apiSuccess {String} chartType 数量－类型
     *
     * @apiSuccess {Long} quantity 数量－售出数量
     * @apiSuccess {String} dateStr 数量－日期
     * @apiSuccess {String} chartType 数量－类型
     *
     * @apiSuccess {Long} quantity 数量－核销数量
     * @apiSuccess {String} dateStr 数量－日期
     * @apiSuccess {String} chartType 数量－类型
     *
     * @apiSuccess {Long} quantity 人数－访客人数
     * @apiSuccess {String} dateStr 人数－日期
     * @apiSuccess {String} chartType 人数－类型
     *
     * @apiSuccess {Long} quantity 人数－下单人数
     * @apiSuccess {String} dateStr 人数－日期
     * @apiSuccess {String} chartType 人数－类型
     *
     * @apiSuccess {Long} quantity 人数－核销人数
     * @apiSuccess {String} dateStr 人数－日期
     * @apiSuccess {String} chartType 人数－类型
     *
     * @apiSuccessExample {json} Success-Response:
     *
     * {
     *   "code": "1",
     *   "desc": "成功",
     *   "data": {
     *     "visitorCount": 5,
     *     "clickCount": 6,
     *     "orderCount": 73,
     *     "orderPayCount": 45,
     *     "verificationCustomerCount": 1,
     *     "verificationCount": 12,
     *     "orderConversionRate": "14",
     *     "orderVerifiCationConversionRate": "0",
     *     "viewCountMonthList": [
     *       {
     *         "quantity": 2,
     *         "chartType": "visit",
     *         "dateStr": "2016/12/08"
     *       },
     *       {
     *         "quantity": 3,
     *         "chartType": "visit",
     *         "dateStr": "2016/12/09"
     *       }
     *     ],
     *     "saleCountMonthList": [
     *       {
     *         "quantity": 29,
     *         "chartType": "sale",
     *         "dateStr": "2016/12/08"
     *       },
     *       {
     *         "quantity": 44,
     *         "chartType": "sale",
     *         "dateStr": "2016/12/09"
     *       }
     *     ],
     *     "verifyCountMonthList": [
     *       {
     *         "quantity": 6,
     *         "chartType": "verify",
     *         "dateStr": "2016/12/08"
     *       },
     *       {
     *         "quantity": 6,
     *         "chartType": "verify",
     *         "dateStr": "2016/12/09"
     *       }
     *     ],
     *     "viewCustomerCountMonthList": [
     *       {
     *         "quantity": 113,
     *         "chartType": "visit",
     *         "dateStr": "2016/12/08"
     *       },
     *       {
     *         "quantity": 127,
     *         "chartType": "visit",
     *         "dateStr": "2016/12/09"
     *       }
     *     ],
     *     "saleCustomerMonthList": [
     *       {
     *         "quantity": 35,
     *         "chartType": "sale",
     *         "dateStr": "2016/12/08"
     *       },
     *       {
     *         "quantity": 35,
     *         "chartType": "sale",
     *         "dateStr": "2016/12/09"
     *       }
     *     ],
     *     "verifyCustomerMonthList": [
     *       {
     *         "quantity": 35,
     *         "chartType": "verify",
     *         "dateStr": "2016/12/08"
     *       },
     *       {
     *         "quantity": 35,
     *         "chartType": "verify",
     *         "dateStr": "2016/12/09"
     *       }
     *     ]
     *   }
     * }
     */
    @RequestMapping(value = Routes.MERCHANT_PRODUCT_STATISTICS, method = RequestMethod.GET)
    public JsonResult index(MerchantProductStatisticsDto dto, HttpServletRequest request) {
        UserInfoDto userInfoDto = userHelper.getSession(request);
        RestDoing doing = jsonResult -> {
            if(!checkDto(dto,jsonResult)) {
                return;
            }
            jsonResult.data = calProductStatistics(userInfoDto,dto,null,true);
        };
        return doing.go(request, log);
    }

    /**
     * @api {get}/merchant/product/statistics/search 产品名称/编号搜索
     * @apiGroup B端 merchant product statistics
     * @apiVersion 1.0.0
     * @apiHeader {String} userToken 用户token
     * @apiHeader {String} domain 请求域名
     *
     * @apiParam {String} searchDateType YESTERDAY("昨天"), WEEK("最近一周"), MONTH("最近一个月"), QUATER("最近三个月")
     * @apiParam {String} startDate 开始时间
     * @apiParam {String} endDate 结束时间
     * @apiParam {String} productSourceType ALL("全部"),SELF("自营"),MARKET("分销") 产品来源类型
     * @apiParam {String} type ALL("全部"),GOODS("商品"),SERVICE("服务") 类型
     * @apiParam {String} keyword 产品名称/编号
     *
     * @apiSuccess {String} productName 产品名称
     * @apiSuccess {Long} productId 产品编号
     * @apiSuccess {String} productSourceType 来源
     * @apiSuccess {Long} salePrice 售价
     * @apiSuccess {String} productShowCount 展示次数
     * @apiSuccess {Integer} clickCount 访问次数
     * @apiSuccess {Integer} visitorCount 访客人数
     * @apiSuccess {Long} orderCount 下单件数
     * @apiSuccess {Long} orderPayCount 支付件数
     * @apiSuccess {Long} verificationCustomerCount 核销人数
     * @apiSuccess {Long} verificationCount 核销数量
     * @apiSuccess {String} orderConversionRate 下单转化率
     * @apiSuccess {String} orderVerifiCationConversionRate 核销转化率
     *
     * @apiSuccessExample {json} Success-Response:
     *
     * {
     *   "code": "1",
     *   "desc": "成功",
     *   "data": {
     *     "data": [
     *       {
     *         "productId": 1172,
     *         "productSourceType": "MARKET",
     *         "visitorCount": 0,
     *         "clickCount": 2,
     *         "orderCount": 7,
     *         "orderPayCount": 1,
     *         "verificationCustomerCount": 1,
     *         "verificationCount": 1,
     *         "orderVerifiCationConversionRate": "1",
     *         "showCount": 1,
     *         "productName": "牛仔裤",
     *         "salePrice": 100
     *       },
     *       {
     *         "productId": 1173,
     *         "productSourceType": "MARKET",
     *         "visitorCount": 0,
     *         "clickCount": 2,
     *         "orderCount": 14,
     *         "orderPayCount": 2,
     *         "verificationCustomerCount": 1,
     *         "verificationCount": 2,
     *         "orderVerifiCationConversionRate": "1",
     *         "showCount": 1,
     *         "productName": "耳环",
     *         "salePrice": 54
     *       },
     *       {
     *         "productId": 1171,
     *         "productSourceType": "MARKET",
     *         "visitorCount": 0,
     *         "clickCount": 2,
     *         "orderCount": 14,
     *         "orderPayCount": 2,
     *         "verificationCustomerCount": 1,
     *         "verificationCount": 2,
     *         "orderVerifiCationConversionRate": "1",
     *         "showCount": 1,
     *         "productName": "帽子",
     *         "salePrice": 50
     *       }
     *     ],
     *     "totalCount": 30,
     *     "totalPage": 3,
     *     "pageNo": 0,
     *     "pageSize": 10
     *   }
     * }
     */
    @RequestMapping(value = Routes.MERCHANT_PRODUCT_STATISTICS_SEARCH, method = RequestMethod.GET)
    public JsonResult search(MerchantProductStatisticsDto dto, HttpServletRequest request) {
        UserInfoDto userInfoDto = userHelper.getSession(request);
        RestDoing doing = jsonResult -> {
            if(!checkDto(dto,jsonResult)) {
                return;
            }
            PageResult<MerchantProductStatisticsDto> pageResult = merchantProductStatisticsService.getProductsStatistics(this.getPage(dto.getPageNo(), dto.getPageSize()),
                    userInfoDto.mall.getId(), userInfoDto.merchant.getId(),dto.getProductId(),dto.getProductSourceType(),
                    dto.getType(),dto.getStartDate(),dto.getEndDate(),dto.getKeyword());
            if(pageResult.data !=null && pageResult.data.size()>0) {
                pageResult.data.forEach(productStatisticsDto -> {
                    calProductStatistics(userInfoDto,dto,productStatisticsDto,false);
                });
            }
            jsonResult.data = pageResult;
        };
        return doing.go(request, log);
    }

    /**
     * @api {get}/merchant/product/statistics/info 产品明细统计
     * @apiGroup B端 merchant product statistics
     * @apiVersion 1.0.0
     * @apiHeader {String} userToken 用户token
     * @apiHeader {String} domain 请求域名
     *
     * @apiParam {String} searchDateType YESTERDAY("昨天"), WEEK("最近一周"), MONTH("最近一个月"), QUATER("最近三个月")
     * @apiParam {String} startDate 开始时间
     * @apiParam {String} endDate 结束时间
     * @apiParam {Long} productId 产品编号
     *
     * @apiSuccess {BigDecimal} salePrice 售价
     * @apiSuccess {BigDecimal} originalPrice 原价
     * @apiSuccess {String} productSourceType 产品来源
     * @apiSuccess {Long} productId 编号
     * @apiSuccess {String} productName 产品名称
     * @apiSuccess {Integer} clickCount 访问次数
     * @apiSuccess {Integer} visitorCount 访客人数
     * @apiSuccess {Long} orderCount 下单件数
     * @apiSuccess {Long} orderPayCount 支付件数
     * @apiSuccess {Long} verificationCustomerCount 核销人数
     * @apiSuccess {Long} verificationCount 核销数量
     * @apiSuccess {String} orderConversionRate 下单转化率
     * @apiSuccess {String} orderVerifiCationConversionRate 核销转化率
     *
     * @apiSuccess {List} viewCountMonthList 按月访问次数　chartType=visit
     * @apiSuccess {List} saleCountMonthList 按月下单数量  chartType=sale
     * @apiSuccess {List} verifyCountMonthList 按月核销数量  chartType=verify
     * @apiSuccess {List} viewCustomerCountMonthList 按月访问人数  chartType=visit
     * @apiSuccess {List} saleCustomerMonthList 按月下单人数  chartType=sale
     * @apiSuccess {List} verifyCustomerMonthList 按月核销人数  chartType=verify
     * @apiSuccess {List} orderConversionRateMonthList 按月下单转化率 chartType=orderRate
     * @apiSuccess {List} orderVerifyConversionRateMonthList 按月核销转化率 chartType=verifyRate
     *
     * @apiSuccess {Long} quantity 数量－访问次数
     * @apiSuccess {String} dateStr 数量－日期
     * @apiSuccess {String} chartType 数量－类型
     *
     * @apiSuccess {Long} quantity 数量－售出数量
     * @apiSuccess {String} dateStr 数量－日期
     * @apiSuccess {String} chartType 数量－类型
     *
     * @apiSuccess {Long} quantity 数量－核销数量
     * @apiSuccess {String} dateStr 数量－日期
     * @apiSuccess {String} chartType 数量－类型
     *
     * @apiSuccess {Long} quantity 人数－访客人数
     * @apiSuccess {String} dateStr 人数－日期
     * @apiSuccess {String} chartType 人数－类型
     *
     * @apiSuccess {Long} quantity 人数－下单人数
     * @apiSuccess {String} dateStr 人数－日期
     * @apiSuccess {String} chartType 人数－类型
     *
     * @apiSuccess {Long} quantity 人数－核销人数
     * @apiSuccess {String} dateStr 人数－日期
     * @apiSuccess {String} chartType 人数－类型
     *
     * @apiSuccessExample {json} Success-Response:
     *
     * {
     *   "code": "1",
     *   "desc": "成功",
     *   "data": {
     *     "productSourceType": "SELF",
     *     "visitorCount": 17,
     *     "clickCount": 6,
     *     "orderCount": 62,
     *     "orderPayCount": 14,
     *     "verificationCustomerCount": 1,
     *     "verificationCount": 9,
     *     "orderConversionRate": "3",
     *     "orderVerifiCationConversionRate": "0",
     *     "viewCountMonthList": [
     *       {
     *         "quantity": 3,
     *         "chartType": "visit",
     *         "dateStr": "2016/12/09"
     *       }
     *     ],
     *     "saleCountMonthList": [
     *       {
     *         "quantity": 44,
     *         "chartType": "sale",
     *         "dateStr": "2016/12/09"
     *       }
     *     ],
     *     "verifyCountMonthList": [
     *       {
     *         "quantity": 6,
     *         "chartType": "verify",
     *         "dateStr": "2016/12/09"
     *       }
     *     ],
     *     "viewCustomerCountMonthList": [
     *       {
     *         "quantity": 127,
     *         "chartType": "visit",
     *         "dateStr": "2016/12/09"
     *       }
     *     ],
     *     "saleCustomerMonthList": [
     *       {
     *         "quantity": 35,
     *         "chartType": "sale",
     *         "dateStr": "2016/12/09"
     *       }
     *     ],
     *     "verifyCustomerMonthList": [
     *       {
     *         "quantity": 35,
     *         "chartType": "verify",
     *         "dateStr": "2016/12/09"
     *       }
     *     ],
     *     "salePrice": 77,
     *     "originalPrice": 88
     *   }
     * }
     */
    @RequestMapping(value = Routes.MERCHANT_PRODUCT_STATISTICS_INFO, method = RequestMethod.GET)
    public JsonResult info(MerchantProductStatisticsDto dto, HttpServletRequest request) {
        UserInfoDto userInfoDto = userHelper.getSession(request);
        RestDoing doing = jsonResult -> {
            if(dto.getProductId()==null) {
                jsonResult.remind("产品ID不允许为空",log);
                return;
            }
            Product product = merchantProductRepository.findOne(dto.getProductId());
            if(product==null) {
                jsonResult.remind("产品记录不存在",log);
                return;
            }
            if(!checkDto(dto,jsonResult)) {
                return;
            }
            MerchantProductStatisticsDto result = calProductStatistics(userInfoDto,dto,null,true);
            result.setOriginalPrice(product.getBasePrice());
            result.setSalePrice(product.getSellPrice());
            result.setProductName(product.getName());
            result.setProductSourceType(product.getMarketId()==null?"SELF":"MARKET");
            jsonResult.data = result;
        };
        return doing.go(request, log);
    }

    /**
     * 获取对应统计数据
     * @param userInfoDto
     * @param dto
     * @return
     */
    private MerchantProductStatisticsDto calProductStatistics(UserInfoDto userInfoDto,MerchantProductStatisticsDto dto,MerchantProductStatisticsDto result,boolean isChart) {
        MerchantProductStatisticsDto productStatisticsDto = null;
        Long productId = null;

        if(userInfoDto==null || dto==null) {
            return productStatisticsDto;
        }
        if(result==null) {
            productStatisticsDto = new MerchantProductStatisticsDto();
            productId = dto.getProductId();
        } else {
            productStatisticsDto = result;
            productId = result.getProductId();
        }

        //访问次数
        Long viewCount = merchantProductStatisticsService.getProductViewCount(userInfoDto.mall.getId(), userInfoDto.merchant.getId(),productId,dto.getProductSourceType(),
                dto.getType(),dto.getStartDate(),dto.getEndDate(),null);
        productStatisticsDto.setClickCount(viewCount==null?0:viewCount.intValue());
        //访客人数
        Long clickCount = merchantProductStatisticsService.getProductViewCustomerCount(userInfoDto.mall.getId(), userInfoDto.merchant.getId(),productId,dto.getProductSourceType(),
                dto.getType(),dto.getStartDate(),dto.getEndDate(),null);
        productStatisticsDto.setVisitorCount(clickCount==null?0:clickCount.intValue());
        //下单件数
        Long orderCount = merchantProductStatisticsService.getProductSaleCount(userInfoDto.mall.getId(), userInfoDto.merchant.getId(),productId,dto.getProductSourceType(),
                dto.getType(),dto.getStartDate(),dto.getEndDate(),null);
        productStatisticsDto.setOrderCount(orderCount==null?0:orderCount);
        //支付件数
        Long orderPayCount=merchantProductStatisticsService.getProductSalePayCount(userInfoDto.mall.getId(), userInfoDto.merchant.getId(),productId,dto.getProductSourceType(),
                dto.getType(),dto.getStartDate(),dto.getEndDate(),null);
        productStatisticsDto.setOrderPayCount(orderPayCount==null?0:orderPayCount);
        //核销人数
        Long verificationCustomerCount = merchantProductStatisticsService.getProductVerifyCustomerCount(userInfoDto.mall.getId(), userInfoDto.merchant.getId(),productId,dto.getProductSourceType(),
                dto.getType(),dto.getStartDate(),dto.getEndDate(),null);
        productStatisticsDto.setVerificationCustomerCount(verificationCustomerCount==null?0:verificationCustomerCount);
        //核销数量
        Long verificationCount=merchantProductStatisticsService.getProductVerifyCount(userInfoDto.mall.getId(), userInfoDto.merchant.getId(),productId,dto.getProductSourceType(),
                dto.getType(),dto.getStartDate(),dto.getEndDate(),null);
        productStatisticsDto.setVerificationCount(verificationCount==null?0:verificationCount);
        //下单人数
        Long productSaleCustomerCount = merchantProductStatisticsService.getProductSaleCustomerCount(userInfoDto.mall.getId(), userInfoDto.merchant.getId(),productId,dto.getProductSourceType(),
                dto.getType(),dto.getStartDate(),dto.getEndDate(),null);
        productSaleCustomerCount = productSaleCustomerCount==null?0:productSaleCustomerCount;
        //下单转化率
        productStatisticsDto.setOrderConversionRate("0");
        if(productStatisticsDto.getVisitorCount()!=null && productStatisticsDto.getVisitorCount().longValue()>0) {
            BigDecimal productSaleCustomerBigDecimal = new BigDecimal(productSaleCustomerCount);
            BigDecimal viewCountBigDecimal = new BigDecimal(productStatisticsDto.getVisitorCount());
            BigDecimal rate = productSaleCustomerBigDecimal.divide(viewCountBigDecimal,4,BigDecimal.ROUND_HALF_UP).multiply(BigDecimal.valueOf(100));
            productStatisticsDto.setOrderConversionRate(String.valueOf(rate.setScale(2, BigDecimal.ROUND_HALF_UP)));
        }
        //核销转化率
        productStatisticsDto.setOrderVerifiCationConversionRate("0");
        if(orderCount!=null && orderCount.longValue()>0) {
            BigDecimal orderCountBigDecimal = new BigDecimal(orderCount);
            BigDecimal verificationCountBigDecimal = new BigDecimal(productStatisticsDto.getVerificationCount());
            BigDecimal verifyRate = verificationCountBigDecimal.divide(orderCountBigDecimal,4,BigDecimal.ROUND_HALF_UP).multiply(BigDecimal.valueOf(100));
            productStatisticsDto.setOrderVerifiCationConversionRate(String.valueOf(verifyRate.setScale(2, BigDecimal.ROUND_HALF_UP)));
        }
        if(isChart) {
            init(dto, dto.getStartDate(), dto.getEndDate());
            //按月访问次数
            List<MerchantProductStatisticsDto> viewMonthList = merchantProductStatisticsService.getProductViewCountByMonth(userInfoDto.mall.getId(), userInfoDto.merchant.getId(), productId, dto.getProductSourceType(),
                    dto.getType(), dto.getStartDate(), dto.getEndDate(), dto.getGroupByType());
            productStatisticsDto.setViewCountMonthList(resetStatisticsChart(dto.getViewCountMonthList(),viewMonthList));
            //按月下单数量
            List<MerchantProductStatisticsDto> saleMonthList = merchantProductStatisticsService.getProductSaleCountByMonth(userInfoDto.mall.getId(), userInfoDto.merchant.getId(), productId, dto.getProductSourceType(),
                    dto.getType(), dto.getStartDate(), dto.getEndDate(), dto.getGroupByType());
            productStatisticsDto.setSaleCountMonthList(resetStatisticsChart(dto.getSaleCountMonthList(),saleMonthList));
            //按月核销数量
            List<MerchantProductStatisticsDto> verifyMonthList = merchantProductStatisticsService.getProductVerifyCountByMonth(userInfoDto.mall.getId(), userInfoDto.merchant.getId(), productId, dto.getProductSourceType(),
                    dto.getType(), dto.getStartDate(), dto.getEndDate(), dto.getGroupByType());
            productStatisticsDto.setVerifyCountMonthList(resetStatisticsChart(dto.getVerifyCountMonthList(),verifyMonthList));
            //按月访问人数
            List<MerchantProductStatisticsDto> viewCustomerMonthList = merchantProductStatisticsService.getProductViewCustomerCountByMonth(userInfoDto.mall.getId(), userInfoDto.merchant.getId(), productId, dto.getProductSourceType(),
                    dto.getType(), dto.getStartDate(), dto.getEndDate(), dto.getGroupByType());
            productStatisticsDto.setViewCustomerCountMonthList(resetStatisticsChart(dto.getViewCustomerCountMonthList(),viewCustomerMonthList));
            //按月下单人数
            List<MerchantProductStatisticsDto> saleCustomerMonthList = merchantProductStatisticsService.getProductSaleCustomerCountByMonth(userInfoDto.mall.getId(), userInfoDto.merchant.getId(), productId, dto.getProductSourceType(),
                    dto.getType(), dto.getStartDate(), dto.getEndDate(), dto.getGroupByType());
            productStatisticsDto.setSaleCustomerMonthList(resetStatisticsChart(dto.getSaleCustomerMonthList(),saleCustomerMonthList));
            //按月核销人数
            List<MerchantProductStatisticsDto> verifyCustomerMonthList = merchantProductStatisticsService.getProductVerifyCustomerCountByMonth(userInfoDto.mall.getId(), userInfoDto.merchant.getId(), productId, dto.getProductSourceType(),
                    dto.getType(), dto.getStartDate(), dto.getEndDate(), dto.getGroupByType());
            productStatisticsDto.setVerifyCustomerMonthList(resetStatisticsChart(dto.getVerifyCustomerMonthList(),verifyCustomerMonthList));
            //按月下单转化率
            productStatisticsDto.setOrderConversionRateMonthList(resetStatisticsChart(dto.getOrderConversionRateMonthList(),calConversionRateMonth("orderRate",saleCustomerMonthList,viewCustomerMonthList)));
            //按月核销转化率
            productStatisticsDto.setOrderVerifyConversionRateMonthList(resetStatisticsChart(dto.getOrderVerifyConversionRateMonthList(),calConversionRateMonth("verifyRate",verifyMonthList,saleMonthList)));
        } else {
            Long showCount = merchantProductStatisticsService.getProductShowCount(userInfoDto.mall.getId(), userInfoDto.merchant.getId(),productId,dto.getProductSourceType(), dto.getType(),dto.getStartDate(),dto.getEndDate());
            productStatisticsDto.setProductShowCount(showCount==null?0:showCount);
        }
        return productStatisticsDto;
    }

    /**
     * 重设统计数据
     * @param dtoList
     * @param statisticsDtoList
     */
    private List<MerchantProductStatisticsDto> resetStatisticsChart(List<MerchantProductStatisticsDto> dtoList,List<MerchantProductStatisticsDto> statisticsDtoList) {
        if(statisticsDtoList==null || statisticsDtoList.size()==0 || dtoList==null || dtoList.size()==0) {
            return dtoList;
        }
        for(MerchantProductStatisticsDto dto : dtoList) {
            MerchantProductStatisticsDto statisticsDto = findDtoByDate(dto.getDateStr(),statisticsDtoList);
            if(statisticsDto!=null) {
                dto.setQuantity(statisticsDto.getQuantity());
                if(dto.getChartType().equals("orderRate") || dto.getChartType().equals("verifyRate")) {
                    dto.setOrderConversionRate(statisticsDto.getOrderConversionRate());
                }
            }
        }
        return dtoList;
    }

    /**
     * 计算转化率
     * @param saleMonthList
     * @param viewCustomerMonthList
     * @return
     */
    private List<MerchantProductStatisticsDto> calConversionRateMonth(String conversionKey,List<MerchantProductStatisticsDto> saleMonthList,List<MerchantProductStatisticsDto> viewCustomerMonthList) {
        Set dateSet = new HashSet<>();
        List<MerchantProductStatisticsDto> resultList=null;
        createDateSet(saleMonthList,dateSet);
        createDateSet(viewCustomerMonthList,dateSet);
        if(dateSet.size()>0) {
            resultList = new ArrayList<>();
            Iterator it=dateSet.iterator();
            while(it.hasNext()) {
                String date = (String) it.next();
                MerchantProductStatisticsDto saleDto = findDtoByDate(date,saleMonthList);
                MerchantProductStatisticsDto viewDto = findDtoByDate(date,viewCustomerMonthList);
                MerchantProductStatisticsDto dto = new MerchantProductStatisticsDto();
                if(saleDto!=null && viewDto!=null) {
                    BigDecimal orderCountBigDecimal = new BigDecimal(saleDto.getQuantity());
                    BigDecimal viewCountBigDecimal = new BigDecimal(viewDto.getQuantity());
                    BigDecimal rate = orderCountBigDecimal.divide(viewCountBigDecimal, 4, BigDecimal.ROUND_HALF_UP).multiply(BigDecimal.valueOf(100));
                    dto.setOrderConversionRate(viewDto.getQuantity()==0?"0":String.valueOf(rate.setScale(2, BigDecimal.ROUND_HALF_UP)));
                } else {
                    dto.setOrderConversionRate("0");
                }
                dto.setDateStr(date);
                dto.setChartType(conversionKey);
                resultList.add(dto);
            }
        }
        return resultList;
    }

    /**
     * 查询对应日期数据
     * @param dateStr
     * @param list
     * @return
     */
    private MerchantProductStatisticsDto findDtoByDate(String dateStr,List<MerchantProductStatisticsDto> list) {
        MerchantProductStatisticsDto dto = null;
        if(list!=null && list.size()>0) {
            for(MerchantProductStatisticsDto p:list) {
                if(dateStr.equals(p.getDateStr())) {
                    return p;
                }
            }
        }
        return dto;
    }

    /**
     * 添加日期到集合
     * @param list
     * @param dateSet
     */
    private void createDateSet(List<MerchantProductStatisticsDto> list,Set dateSet) {
        if(list!=null && list.size()>0) {
            for(MerchantProductStatisticsDto dto:list) {
                dateSet.add(dto.getDateStr());
            }
        }
    }

    /**
    * 检查表单数据
    * @param dto
    * @param jsonResult
    */
    private boolean checkDto(MerchantProductStatisticsDto dto,JsonResult jsonResult) {
        String searchDateType = dto.getSearchDateType();
        String startDate = dto.getStartDate();
        String endDate = dto.getEndDate();
        String productSourceType = dto.getProductSourceType();
        String type = dto.getType();
        if (StringUtils.isNotBlank(searchDateType) && !EnumUtils.isValidEnum(StatististicsType.class, searchDateType)) {
            jsonResult.remind("searchDateType 必须为 YESTERDAY(\"昨天\"), WEEK(\"最近一周\"), MONTH(\"最近一个月\"), QUATER(\"最近三个月\")",log);
            return false;
        }
        if (StringUtils.isNotBlank(productSourceType) && !EnumUtils.isValidEnum(MerchantOrderSourceType.class, productSourceType)) {
            jsonResult.remind("productSourceType 必须为ALL(\"全部\"), SELF(\"自营\"), MARKET(\"分销\")",log);
            return false;
        }
        if (StringUtils.isNotBlank(type) && !EnumUtils.isValidEnum(ProductType.class, type)) {
            jsonResult.remind("type 必须为 ALL(\"全部\"), GOODS(\"商品\"), SERVICE(\"服务\")",log);
            return false;
        }
        if (StringUtils.isNotBlank(searchDateType)) {
            //昨天
            if (StatististicsType.YESTERDAY == StatististicsType.valueOf(searchDateType)) {
                Date today = DateUtils.getCurrentDate(DateFormatUtils.DATE_FORMAT1);
                startDate = DateUtils.addDayToDate(-1,today,DateFormatUtils.DATE_FORMAT1);
                endDate = DateUtils.addDayToDate(-1,today,DateFormatUtils.DATE_FORMAT1);
            }
            //每周
            if (StatististicsType.WEEK == StatististicsType.valueOf(searchDateType)) {
                Date today = DateUtils.getCurrentDate(DateFormatUtils.DATE_FORMAT1);
                startDate = DateUtils.addDayToDate(-6, today,DateFormatUtils.DATE_FORMAT1);
                endDate = DateUtils.getCurrentTime(DateFormatUtils.DATE_FORMAT1);
            }
            //近一个月
            if (StatististicsType.MONTH == StatististicsType.valueOf(searchDateType)) {
                Date today = DateUtils.getCurrentDate(DateFormatUtils.DATE_FORMAT1);
                startDate = DateUtils.addMothToDate(-1,today,DateFormatUtils.DATE_FORMAT1);
                endDate = DateUtils.getCurrentTime(DateFormatUtils.DATE_FORMAT1);
            }
            //近三个月
            if (StatististicsType.QUATER == StatististicsType.valueOf(searchDateType)) {
                Date today = DateUtils.getCurrentDate(DateFormatUtils.DATE_FORMAT1);
                startDate = DateUtils.addMothToDate(-3,today,DateFormatUtils.DATE_FORMAT1);
                endDate = DateUtils.getCurrentTime(DateFormatUtils.DATE_FORMAT1);
            }
        }
        if(StringUtils.isNotBlank(startDate) && StringUtils.isNotBlank(endDate)) {
            int days = DateUtils.compareDate(startDate,endDate,0);
            if(days==0) {
                dto.setGroupByType("hour");
            } else if(days>0 && days<=31) {
                dto.setGroupByType("day");
            } else if(days > 31) {
                dto.setGroupByType("month");
            }
        }
        if(StringUtils.isNotBlank(startDate)) {
            dto.setStartDate(startDate+" 00:00:00");
        }
        if(StringUtils.isNotBlank(endDate)) {
            dto.setEndDate(endDate+" 23:59:59");
        }
        return true;
    }

    /**
     * 初始化月日小时数据
     * @throws Exception
     */
    private void init(MerchantProductStatisticsDto dto, String startDate, String endDate) {
        List<MerchantProductStatisticsDto> viewCountMonthList = new ArrayList<>();//按月访问次数
        List<MerchantProductStatisticsDto> saleCountMonthList = new ArrayList<>();//按月下单数量
        List<MerchantProductStatisticsDto> verifyCountMonthList = new ArrayList<>();//按月核销数量

        List<MerchantProductStatisticsDto> viewCustomerCountMonthList = new ArrayList<>();//按月访问人数
        List<MerchantProductStatisticsDto> saleCustomerMonthList = new ArrayList<>();//按月下单人数
        List<MerchantProductStatisticsDto> verifyCustomerMonthList = new ArrayList<>();//按月核销人数

        List<MerchantProductStatisticsDto> orderConversionRateMonthList = new ArrayList<>();//按月下单转化率
        List<MerchantProductStatisticsDto> orderVerifyConversionRateMonthList = new ArrayList<>();//按月核销数量

        dto.setViewCountMonthList(viewCountMonthList);
        dto.setSaleCountMonthList(saleCountMonthList);
        dto.setVerifyCountMonthList(verifyCountMonthList);
        dto.setViewCustomerCountMonthList(viewCustomerCountMonthList);
        dto.setSaleCustomerMonthList(saleCustomerMonthList);
        dto.setVerifyCustomerMonthList(verifyCustomerMonthList);
        dto.setOrderConversionRateMonthList(orderConversionRateMonthList);
        dto.setOrderVerifyConversionRateMonthList(orderVerifyConversionRateMonthList);

        startDate = startDate.substring(0,10);
        endDate = endDate.substring(0,10);
        int days = DateUtils.compareDate(startDate,endDate,0);
        if(days>=0 && StringUtils.isNotEmpty(startDate)) {
            if(dto.getGroupByType().equals("hour")) {
                for(int i = 0; i < 24; i++) {
                    String hour = i>9?String.valueOf(i):"0"+i;
                    viewCountMonthList.add(initMerchantProductStatisticsDto(hour,"visit"));
                    saleCountMonthList.add(initMerchantProductStatisticsDto(hour,"sale"));
                    verifyCountMonthList.add(initMerchantProductStatisticsDto(hour,"verify"));

                    viewCustomerCountMonthList.add(initMerchantProductStatisticsDto(hour,"visit"));
                    saleCustomerMonthList.add(initMerchantProductStatisticsDto(hour,"sale"));
                    verifyCustomerMonthList.add(initMerchantProductStatisticsDto(hour,"verify"));

                    orderConversionRateMonthList.add(initMerchantProductStatisticsDto(hour,"orderRate"));
                    orderVerifyConversionRateMonthList.add(initMerchantProductStatisticsDto(hour,"verifyRate"));

                }
            } else if(dto.getGroupByType().equals("day")) {
                for (int i = 0; i <= days; i++) {
                    String date = DateUtils.addDayToDate(i,startDate,DateFormatUtils.DATE_FORMAT1);
                    date = date.replace("-","/");
                    viewCountMonthList.add(initMerchantProductStatisticsDto(date,"visit"));
                    saleCountMonthList.add(initMerchantProductStatisticsDto(date,"sale"));
                    verifyCountMonthList.add(initMerchantProductStatisticsDto(date,"verify"));

                    viewCustomerCountMonthList.add(initMerchantProductStatisticsDto(date,"visit"));
                    saleCustomerMonthList.add(initMerchantProductStatisticsDto(date,"sale"));
                    verifyCustomerMonthList.add(initMerchantProductStatisticsDto(date,"verify"));

                    orderConversionRateMonthList.add(initMerchantProductStatisticsDto(date,"orderRate"));
                    orderVerifyConversionRateMonthList.add(initMerchantProductStatisticsDto(date,"verifyRate"));
                }
            } else if(dto.getGroupByType().equals("month")) {
                int monthNum = DateUtils.compareDate(startDate,endDate,1)+1;
                for (int i = 0; i < monthNum; i++) {
                    String currentMonth = DateUtils.addMothToDate(i,startDate,DateFormatUtils.DATE_FORMAT1);
                    String yearMonth = currentMonth.replace("-","/").substring(0,7);
                    viewCountMonthList.add(initMerchantProductStatisticsDto(yearMonth,"visit"));
                    saleCountMonthList.add(initMerchantProductStatisticsDto(yearMonth,"sale"));
                    verifyCountMonthList.add(initMerchantProductStatisticsDto(yearMonth,"verify"));

                    viewCustomerCountMonthList.add(initMerchantProductStatisticsDto(yearMonth,"visit"));
                    saleCustomerMonthList.add(initMerchantProductStatisticsDto(yearMonth,"sale"));
                    verifyCustomerMonthList.add(initMerchantProductStatisticsDto(yearMonth,"verify"));

                    orderConversionRateMonthList.add(initMerchantProductStatisticsDto(yearMonth,"orderRate"));
                    orderVerifyConversionRateMonthList.add(initMerchantProductStatisticsDto(yearMonth,"verifyRate"));
                }
            } else if(dto.getGroupByType().equals("year")) {
                int startYear = DateUtils.getCurrentYear(startDate);
                int endYear = DateUtils.getCurrentYear(endDate);
                for(;startYear<=endYear;startYear++) {
                    String year = String.valueOf(startYear);
                    viewCountMonthList.add(initMerchantProductStatisticsDto(year,"visit"));
                    saleCountMonthList.add(initMerchantProductStatisticsDto(year,"sale"));
                    verifyCountMonthList.add(initMerchantProductStatisticsDto(year,"verify"));

                    viewCustomerCountMonthList.add(initMerchantProductStatisticsDto(year,"visit"));
                    saleCustomerMonthList.add(initMerchantProductStatisticsDto(year,"sale"));
                    verifyCustomerMonthList.add(initMerchantProductStatisticsDto(year,"verify"));

                    orderConversionRateMonthList.add(initMerchantProductStatisticsDto(year,"orderRate"));
                    orderVerifyConversionRateMonthList.add(initMerchantProductStatisticsDto(year,"verifyRate"));
                }
            }
        }
    }

    /**
     * 初始化MerchantProductStatisticsDto数据
     * @param date
     * @return
     * @throws Exception
     */
    private MerchantProductStatisticsDto initMerchantProductStatisticsDto(String date, String chartType) {
        MerchantProductStatisticsDto dto = new MerchantProductStatisticsDto();
        dto.setQuantity(0L);
        dto.setChartType(chartType);
        dto.setDateStr(date);
        dto.setOrderConversionRate("0");
        return dto;
    }
}
